package com.steven.logserver.listener;

import com.steven.logserver.config.ZookeeperConfig;
import org.apache.curator.framework.CuratorFramework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

import java.net.InetAddress;

/**
 * 程序停止事件监听器
 *
 * TIPS：是不是可以使用Runtime.getRuntime().addShutdownHook()来实现同样效果？作用：在jvm中增加一个关闭的钩子，当jvm关闭的时候，
 *       会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子，当系统执行完这些钩子后，jvm才会关闭。所以这些钩子可以
 *       在jvm关闭的时候进行内存清理、对象销毁等操作
 *
 * @author qinxh
 * @date 2016/10/31
 */
@Component
public class CloseListener implements ApplicationListener<ContextClosedEvent> {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${log.netty.bind.port}")
    private Integer bindPort;

    @Value("${log.netty.server.client-number}")
    private String clientNumberPath;

    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {

        logger.info("------> 程序停止，关闭netty服务节点对应的客户端分布式计数器节点");
        try {
            CuratorFramework client = ZookeeperConfig.getClient();
            String path = clientNumberPath + InetAddress.getLocalHost().getHostAddress() + ":" + bindPort;
            if(client.checkExists().forPath(path) != null){
                client.delete()
                        // 如果删除失败，那么在会继续执行，直到成功
                        .guaranteed()
                        // 如果有子节点，则递归删除
                        .deletingChildrenIfNeeded()
                        .forPath(path);
                logger.info("关闭netty服务节点对应的客户端分布式计数器节点成功 <------");
            }
        } catch (Exception e) {
            logger.error("关闭netty服务节点对应的客户端分布式计数器节点失败：{}", e.getMessage());
        }
    }
}
